/*
 * PhotonRTOS础光实时操作系统 -- CPU初始化相关文件
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 * ld script to make ARM PhotonRTOS kernel
 * taken from the i386 version by Russell King
 * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
 */

#include <photon/photon.lds.h>
#include <asm/process.h>
#include "image.h"

/* .exit.text needed in case of alternative patching */
#define ARM_EXIT_KEEP(x)	x
#define ARM_EXIT_DISCARD(x)

OUTPUT_ARCH(arm)

jiffies = jiffies_64;

#define PECOFF_EDATA_PADDING
#define ALIGN_DEBUG_RO		. = ALIGN(4);
#define ALIGN_DEBUG_RO_MIN(min) . = ALIGN(min);

#if defined(CONFIG_ARCH_BSTA1000_R5)
MEMORY
{
    RAM (xrw)  : ORIGIN = 0x18080000, LENGTH = 0x80000 /* to 0x18080000 - 0x18100000 */
}
#endif

#if defined(CONFIG_ARCH_XILINX_CORTEXR5)
MEMORY
{
    RAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 4M /* to 0x21FFFFFF = 0xFFFFFF */
    ATCM (xr) : ORIGIN = 0x00000000, LENGTH = 32k /* to 0x00003FFF = 0x007FFFFF*/
}
#endif

#if defined(CONFIG_ARCH_MPS2_CORTEXM3)
/**
 * 调试没有搬移数据段
 * 正常存在flash中，需要修改空间，搬移数据段
 */
MEMORY
{
	FLASH (xr) : ORIGIN = 0x00000000, LENGTH = 256k
	RAM (xrw)  : ORIGIN = 0x00040000, LENGTH = 1M
}
#endif
_estack = ORIGIN(RAM) + LENGTH(RAM);

ENTRY(Reset_Handler)

_Min_Heap_Size = 0x300000 ;        /* Required amount of heap. */
_Min_Stack_Size = 0x4000 ;       /* Required amount of stack. */
M_VECTOR_RAM_SIZE = 192 * 4;
#if defined(CONFIG_CPU_CORTEX_M)
/* M核链接文件 */
SECTIONS
{
	/DISCARD/ : {
		ARM_EXIT_DISCARD(EXIT_TEXT)
		ARM_EXIT_DISCARD(EXIT_DATA)
		EXIT_CALL
		*(.discard)
		*(.discard.*)
	}

	.isr_vector :
	{
	    __vector_table = .;
	    KEEP(*(.isr_vector))
	    . = ALIGN(4);
	} > FLASH

	. = 0 + TEXT_OFFSET;

	.head.text : {
	    kernel_text_start = .;
		HEAD_TEXT
	} > FLASH

	. = ALIGN(4);
	.text : {
		_stext = .;
			__exception_text_start = .;
			*(.exception.text)
			__exception_text_end = .;
			IRQENTRY_TEXT
			TEXT_TEXT
			SCHED_TEXT
			LOCK_TEXT
			*(.fixup)
			*(.gnu.warning)
		. = ALIGN(4);
		*(.got)
	} > FLASH

	ALIGN_DEBUG_RO
	RO_DATA(4)
	EXCEPTION_TABLE(4)
	NOTES
	ALIGN_DEBUG_RO
	_etext = .;			/* text 和 rodata 段结束 */

	ALIGN_DEBUG_RO_MIN(4)
	__init_begin = .;

	INIT_TEXT_SECTION(4)
	.exit.text : {
		ARM_EXIT_KEEP(EXIT_TEXT)
	} > FLASH

	_sidata = LOADADDR(.init.data);
	ALIGN_DEBUG_RO_MIN(4)
	.init.data : {
	        _sdata = .;
		INIT_DATA
		INIT_SETUP(4)
		INIT_CALLS
		CON_INITCALL
		SECURITY_INITCALL
		INIT_RAM_FS
	}> RAM AT > FLASH
	.exit.data : {
		ARM_EXIT_KEEP(EXIT_DATA)
	}> RAM AT > FLASH

	. = ALIGN(4);
	__init_end = .;

	. = ALIGN(4);
	.altinstructions : {
		__alt_instructions = .;
		*(.altinstructions)
		__alt_instructions_end = .;
	}> RAM AT > FLASH
	.altinstr_replacement : {
		*(.altinstr_replacement)
	}> RAM AT > FLASH

	. = ALIGN(4);
	_data = .;

	RW_DATA_SECTION(4, 4, 4)
	PECOFF_EDATA_PADDING
	_edata = .;
	BSS_SECTION(0, 0, 0)

	. = ALIGN(4);
	idmap_pg_dir = .;
	. += IDMAP_DIR_SIZE;
	global_pg_dir = .;

	kernel_text_end = .;

	STABS_DEBUG

	HEAD_SYMBOLS
}
#endif


#if defined(CONFIG_CPU_CORTEX_R)
SECTIONS
{
	/*
	 * XXX: The linker does not define how output sections are
	 * assigned to input sections when there are multiple statements
	 * matching the same input section name.  There is no documented
	 * order of matching.
	 */
	/DISCARD/ : {
		ARM_EXIT_DISCARD(EXIT_TEXT)
		ARM_EXIT_DISCARD(EXIT_DATA)
		EXIT_CALL
		*(.discard)
		*(.discard.*)
	}

	. = 0 + TEXT_OFFSET;

	.head.text : {
		kernel_text_start = .;
	} > ATCM

	. = ALIGN(4);
	.text : {			/* Real text segment		*/
		_stext = .;		/* Text and read-only data	*/
			__exception_text_start = .;
			*(.exception.text)
			__exception_text_end = .;
			IRQENTRY_TEXT
			TEXT_TEXT
			SCHED_TEXT
			LOCK_TEXT
			*(.fixup)
			*(.gnu.warning)
		. = ALIGN(4);
		*(.got)			/* Global offset table		*/
	}

	ALIGN_DEBUG_RO
	RO_DATA(4)
	EXCEPTION_TABLE(4)
	NOTES
	ALIGN_DEBUG_RO
	_etext = .;			/* End of text and rodata section */

	ALIGN_DEBUG_RO_MIN(4)
	__init_begin = .;

	INIT_TEXT_SECTION(4)
	.exit.text : {
		ARM_EXIT_KEEP(EXIT_TEXT)
	}

	ALIGN_DEBUG_RO_MIN(4)
	.init.data : {
		INIT_DATA
		INIT_SETUP(4)
		INIT_CALLS
		CON_INITCALL
		SECURITY_INITCALL
		INIT_RAM_FS
	}
	.exit.data : {
		ARM_EXIT_KEEP(EXIT_DATA)
	}

	. = ALIGN(4);
	__init_end = .;

	. = ALIGN(4);
	.altinstructions : {
		__alt_instructions = .;
		*(.altinstructions)
		__alt_instructions_end = .;
	}
	.altinstr_replacement : {
		*(.altinstr_replacement)
	}

	. = ALIGN(4);
	_data = .;
	_sdata = .;
	RW_DATA_SECTION(4, 4, 4)
	PECOFF_EDATA_PADDING
	_edata = .;

	BSS_SECTION(0, 0, 0)

	. = ALIGN(4);
	idmap_pg_dir = .;
	. += IDMAP_DIR_SIZE;
	global_pg_dir = .;

	kernel_text_end = .;

	STABS_DEBUG

	HEAD_SYMBOLS
	    /* Set stack top to end of SRAM, and stack limit move down by
     * size of stack_dummy section */
    __AbdStack = _estack - 4;
    __SwiStack = __AbdStack - 0x400;
    __FiqStack = __SwiStack - 0x400;
    __UndStack = __FiqStack - 0x400;
    __IrqStack = __UndStack - 0x400;

    __AbdStack1 = __IrqStack - 0x800;
    __SwiStack1 = __AbdStack1 - 0x400;
    __FiqStack1 = __SwiStack1 - 0x400;
    __UndStack1 = __FiqStack1 - 0x400;
    __IrqStack1 = __UndStack1 - 0x400;
}
#endif

/*
 * The HYP init code and ID map text can't be longer than a page each,
 * and should not cross a page boundary.
 */
/*ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,
	"ID map text too big or misaligned")*/

/*
 * If padding is applied before .head.text, virt<->phys conversions will fail.
 */
/*ASSERT(kernel_text_start == (KERNEL_VA_START + TEXT_OFFSET), "HEAD is misaligned")*/
